package szhn.service.impl;

import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import lombok.extern.slf4j.Slf4j;
import szhn.mapper.BookMapper;
import szhn.model.BookModel;
import szhn.service.BookService;
import szhn.util.RedisUtil;

@Service
@Slf4j
public class BookServiceImpl implements BookService {
	
	@Resource
	private RedisUtil redisUtil;
	
	@Autowired
	private BookMapper bookMapper;

	@Override
	public Page<BookModel> query(String bookName){
		log.info("BookServiceImpl查询图书记录bookName={}", bookName);
		return bookMapper.query(bookName);
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public boolean save(BookModel bookModel) {
		log.info("BookServiceImpl保存图书bookModel={}", JSON.toJSONString(bookModel));
		boolean flag = bookMapper.save(bookModel);
		
		//当保存成功时，更新缓存
		if(flag) {
			List<Object> bookList = redisUtil.lGet("bookList", 0, -1);
			if(null == bookList) {
				List<BookModel> dbBookList = bookMapper.queryAllBook();
				redisUtil.lSet("bookList", dbBookList, 30 * 60L);
			}else {
				bookList.add(bookModel);
				redisUtil.lSet("bookList", bookList, 30 * 60L);
			}
		}
		
		return flag;
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean modify(BookModel bookModel) {
		log.info("BookServiceImpl修改图书bookModel={}", JSON.toJSONString(bookModel));
		boolean flag = bookMapper.modify(bookModel);
		
		//当修改成功时，更新缓存
		if(flag) {
			List<Object> bookList = redisUtil.lGet("bookList", 0, -1);
			if(null == bookList) {
				List<BookModel> dbBookList = bookMapper.queryAllBook();
				redisUtil.lSet("bookList", dbBookList, 30 * 60L);
			}else {
				for(int i = 0; i < bookList.size(); i++) {
					BookModel cacheBookModel = (BookModel)bookList.get(i);
					if(cacheBookModel.getId().equals(bookModel.getId())) {
						redisUtil.lUpdateIndex("bookList", i, bookModel);
						break;
					}
				}
			}
		}
		
		return flag;
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean delete(String id, String username) {
		log.info("BookServiceImpl删除图书id={},username={}", id, username);
		boolean flag = bookMapper.delete(id, username);
		
		//当修改成功时，更新缓存
		if(flag) {
			List<Object> bookList = redisUtil.lGet("bookList", 0, -1);
			if(null == bookList) {
				List<BookModel> dbBookList = bookMapper.queryAllBook();
				redisUtil.lSet("bookList", dbBookList, 30 * 60L);
			}else {
				Iterator<Object> iterator = bookList.iterator();
				while (iterator.hasNext()) {
					BookModel cacheBookModel = (BookModel)iterator.next();
					if(cacheBookModel.getId().equals(id)) {
						iterator.remove();
						break;
					}
				}
				redisUtil.lSet("bookList", bookList, 30 * 60L);
			}
		}
		
		return flag;
	}
	
	@Override
	public PageInfo<Object> query(int pageNum, int pageSize){
		log.info("BookServiceImpl查询图书缓存pageNum={},pageSize={}", pageNum, pageSize);
		//缓存个数
		long count = redisUtil.lGetListSize("bookList");
		List<Object> resultBookList = null;
		//当缓存不存在时，查库
		if(count == 0) {
			List<BookModel> dbBookList = bookMapper.queryAllBook();
			//此处直接加LIST对象，在分页时会出问题，redis会将整个list当成一个对象，所以需要单独加
			for(BookModel bookModel : dbBookList) {
				redisUtil.lSet("bookList", bookModel);
			}
			count = redisUtil.lGetListSize("bookList");
		}
		
		resultBookList = redisUtil.lGet("bookList", (pageNum - 1) * pageSize, pageNum * pageSize - 1);
		PageHelper.startPage(pageNum, pageSize);
		PageInfo<Object> page = new PageInfo<Object>(resultBookList) ;
		page.setTotal(count);
		int pages = (int) (count/pageNum) + 1;
		page.setPages(pages);
		
		return page;
	}
}
